package com.cenxi.dao.manage;

import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cenxi.common.convert.AccountConvert;
import com.cenxi.common.dto.AccountDTO;
import com.cenxi.common.exceptions.ServiceException;
import com.cenxi.common.result.PageReq;
import com.cenxi.common.result.PageResp;
import com.cenxi.common.result.Req;
import com.cenxi.common.result.Resp;
import com.cenxi.common.vo.AccountVO;
import com.cenxi.dao.entity.Account;
import com.cenxi.dao.entity.AccountRole;
import com.cenxi.dao.mapper.AccountMapper;
import com.cenxi.dao.mapper.AccountRoleMapper;
import com.cenxi.dao.mapper.RoleMapper;
import com.cenxi.utils.constants.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author cenxi
 * @Date 2023/8/16 11:49
 * @Version 1.0
 */
@Slf4j
@Component
public class ManageAccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountRoleMapper accountRoleMapper;

    @Resource
    private AccountConvert accountConvert;

    public PageResp<AccountVO> page(PageReq<AccountDTO> req) {
        AccountDTO data = req.getData();
        if (Objects.isNull(data)) {
            return PageResp.succeed(0, 0,
                    Boolean.FALSE, Collections.emptyList());
        }
        LambdaQueryWrapper<Account> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Account::getDeleted, Constants.ENABLE)
                .eq(Objects.nonNull(data.getState()), Account::getState, data.getState())
                .like(StringUtils.isNotBlank(data.getAccount()), Account::getAccount, data.getAccount())
                .orderByDesc(Account::getUpdateTime);
        if (!CollectionUtils.isEmpty(data.getRoles())) {
            List<Long> accountIds = accountRoleMapper.selectList(new LambdaQueryWrapper<AccountRole>()
                            .in(AccountRole::getRoleId, data.getRoles())).stream()
                    .map(AccountRole::getAccountId).collect(Collectors.toList());
            lqw.in(!CollectionUtils.isEmpty(accountIds), Account::getId, accountIds);
        }
        Page<Account> accountPage = accountMapper.selectPage(new Page<>(req.getPageIndex(), req.getPageSize()), lqw);
        return PageResp.succeed(accountPage.getPages(), accountPage.getTotal(),
                accountPage.hasNext(), accountPage.getRecords().stream()
                        .map(item -> accountConvert.toVO(item)).collect(Collectors.toList()));
    }

    @Transactional(rollbackFor = Exception.class)
    public Resp<Boolean> create(Req<AccountDTO> req) {
        // 新增账号
        AccountDTO data = req.getData();
        if (Objects.isNull(data)) {
            throw new ServiceException("账号创建失败-错误参数");
        }
        Account account = accountConvert.toEntity(data);
        String code = "\\w{1,20}";
        if (!account.getAccount().matches(code) || !account.getPassword().matches(code)) {
            return Resp.error("账号或密码格式不对");
        }
        if (account.getState() < 0 || account.getState() > 1) {
            return Resp.error("账号状态有误");
        }
        // 检验账户是否已存在
        if (accountMapper.exists(new LambdaQueryWrapper<Account>()
                .eq(Account::getAccount, account.getAccount())
                .eq(Account::getState, Constants.ENABLE))) {
            return Resp.error("账号创建-账户已存在");
        }
        // 加密 密码
        account.setPassword(new MD5().digestHex16(account.getPassword()));
        if (accountMapper.insert(account) > 0 && !CollectionUtils.isEmpty(data.getRoles())) {
            // 添加角色
            for (Long role : data.getRoles()) {
                AccountRole accountRole = new AccountRole();
                accountRole.setAccountId(account.getId());
                accountRole.setRoleId(role);
                accountRoleMapper.insert(accountRole);
            }
        }
        return Resp.succeed(Boolean.TRUE);
    }

    public Resp<AccountVO> findById(Long data) {
        return Resp.succeed(accountConvert.toVO(accountMapper.selectById(data)));
    }

    @Transactional(rollbackFor = Exception.class)
    public Resp<Boolean> edit(Req<AccountDTO> req) {
        AccountDTO data = req.getData();
        if (Objects.isNull(data)) {
            throw new ServiceException("账号修改-错误参数");
        }
        Account acc = accountMapper.selectById(data.getId());
        if (Objects.nonNull(acc) && !acc.getAccount().equals(data.getAccount())
                && accountMapper.exists(new LambdaQueryWrapper<Account>()
                .eq(Account::getAccount, data.getAccount())
                .eq(Account::getState, Constants.ENABLE))) {
            return Resp.error("账号修改-账户已存在");
        }
        Account account = accountConvert.toEntity(data);
        if (accountMapper.updateById(account) > 0) {
            // 修改角色/ 先删后加
            if (!CollectionUtils.isEmpty(data.getRoles())) {
                accountRoleMapper.delete(new LambdaQueryWrapper<AccountRole>()
                        .eq(AccountRole::getAccountId, account.getId()));
                for (Long role : data.getRoles()) {
                    AccountRole accountRole = new AccountRole();
                    accountRole.setAccountId(account.getId());
                    accountRole.setRoleId(role);
                    accountRoleMapper.insert(accountRole);
                }
            }
            return Resp.succeed(Boolean.TRUE);
        }
        return Resp.succeed(Boolean.FALSE);
    }

    public Resp<Boolean> enable(List<Long> data, byte enable) {
        if (CollectionUtils.isEmpty(data)) {
            return Resp.error("账号启用-id错误");
        }
        for (Long id : data) {
            Account account = new Account();
            account.setId(id);
            account.setState((int) enable);
            accountMapper.updateById(account);
        }
        return Resp.succeed(Boolean.TRUE);
    }

    public Resp<Boolean> disable(List<Long> data, byte disable) {
        if (CollectionUtils.isEmpty(data)) {
            return Resp.error("账号禁用-id错误");
        }
        for (Long id : data) {
            Account account = new Account();
            account.setId(id);
            account.setState((int) disable);
            accountMapper.updateById(account);
        }
        return Resp.succeed(Boolean.TRUE);
    }

    public Resp<Boolean> deleteById(List<Long> data) {
        if (CollectionUtils.isEmpty(data)) {
            return Resp.error("账号删除-id错误");
        }
        return Resp.succeed(accountMapper.deleteBatchIds(data) > 0);
    }
}
